package com.lhczf.lucenedb.service;

import com.lhczf.lucenedb.bean.SystemConfig;
import com.lhczf.lucenedb.util.BeanUtil;
import com.lhczf.lucenedb.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author: 刘华春
 * @date: 2019/2/6
 */
@Component
@Slf4j
public class ZipServer {

    static final int BUFFER = 8192;

    private ZipServer() {
    }

    public boolean initZipInfoAndZip(String root) {
        SystemConfig config = BeanUtil.getInstance().getBean(SystemConfig.class);
        String backDir = config.getBackupData();
        String dayName = root.substring(root.lastIndexOf(File.separator) + 1);

        File file = new File(root);
        file = FileUtil.findParentFile(file);
        if (file == null) {
            return false;
        }
        String indexName = file.getName();
        String zipName = indexName + "_" + dayName + "_back.zip";
        File zipFile = new File(backDir + File.separator + zipName);
        if (zipFile.exists()) {
            log.warn("之前备份过当天的文件：{}", zipName);
            FileUtil.deleteFile(zipFile);
        }
        return compress(zipFile, root);
    }

    private boolean compress(File destFile, String root) {
        try (FileOutputStream fileOutputStream = new FileOutputStream(destFile)) {
            try (ZipOutputStream out = new ZipOutputStream(fileOutputStream)) {
                String basedir = "";
                File file = new File(root);
                File[] dirs = file.listFiles();
                if (dirs == null) {
                    log.warn("被压缩的目录下没有数据: {}", root);
                    return false;
                }
                for (File dir : dirs) {
                    if (!dir.exists()) {
                        log.warn("被压缩的目录不存在.{}", file.getAbsolutePath());
                    } else {
                        compress(dir, out, basedir);
                    }
                }
            }
        } catch (IOException e) {
            log.error("", e);
        }
        return true;
    }

    private void compress(File file, ZipOutputStream out, String basedir) {
        /* 判断是目录还是文件 */
        if (file.isDirectory()) {
            compressDirectory(file, out, basedir);
        } else {
            compressFile(file, out, basedir);
        }
    }

    /**
     * 压缩一个目录
     */
    private void compressDirectory(File dir, ZipOutputStream out, String basedir) {
        if (!dir.exists()) {
            return;
        }
        File[] files = dir.listFiles();
        for (int i = 0; i < files.length; i++) {
            compress(files[i], out, basedir + dir.getName() + File.separator);
        }
    }

    /**
     * 压缩一个文件
     */
    private void compressFile(File file, ZipOutputStream out, String basedir) {
        if (!file.exists()) {
            return;
        }
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
            ZipEntry entry = new ZipEntry(basedir + file.getName());
            out.putNextEntry(entry);
            int count;
            byte[] data = new byte[BUFFER];
            while ((count = bis.read(data, 0, BUFFER)) != -1) {
                out.write(data, 0, count);
            }
        } catch (IOException e) {
            log.error("", e);
            log.debug("压缩文件异常：{}", basedir + file.getName());
        }
    }
}
